/**
	Copyright (C) 2009,2010  Tobias Domhan

    This file is part of AndOpenGLCam.

    AndObjViewer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AndObjViewer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AndObjViewer.  If not, see <http://www.gnu.org/licenses/>.
 
 */
package com.colladaviewer.android.camera;


import java.io.Writer;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.concurrent.locks.ReentrantLock;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Bitmap.Config;
import android.opengl.GLDebugHelper;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

/**
 * Opens the camera and displays the output on a square (as a texture)
 * @author Tobias Domhan
 *
 */
public class CamFrameSink implements PreviewFrameSink
{

	private boolean frameEnqueued = false;

	private Bitmap screenshot;
	private Object screenshotMonitor = new Object();
	private boolean screenshotTaken = false;
	
	private byte[] frameData = new byte[1];
	private ReentrantLock frameLock = new ReentrantLock();
	

	
	private Writer log = new LogWriter();


	
	/**
	 * mode, being either GL10.GL_RGB or GL10.GL_LUMINANCE
	 */
	private int mode = GL10.GL_RGB;
	
	/**
	 * the default constructer
	 * @param int the {@link PixelFormat} of the Camera preview
	 * @param res Resources
	 * @param customRenderer non AR renderer, may be null
	 */
	public CamFrameSink() 
	{

	}
		
	public byte[] getFrame()
	{
	    byte[] frame = null;
	    if (frameEnqueued)
	    {	        
	        this.getFrameLock().lock();
	        	        
	        // Create a deep clone	        
            frame = new byte[frameData.length];    	        
	        System.arraycopy( frameData, 0, frame, 0, frameData.length );	        	        
	        frameEnqueued = false;
	        
	        this.getFrameLock().unlock();
	        
	    }
	    return frame;
	}

	/* (non-Javadoc)
	
	/**
	 * Make a direct NIO FloatBuffer from an array of floats
	 * @param arr The array
	 * @return The newly created FloatBuffer
	 */
	protected static FloatBuffer makeFloatBuffer(float[] arr) {
		ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer fb = bb.asFloatBuffer();
		fb.put(arr);
		fb.position(0);
		return fb;
	}


	/* (non-Javadoc)
	 * @see edu.dhbw.andopenglcam.interfaces.PreviewFrameSink#setNextFrame(java.nio.ByteBuffer)
	 */
	public final void setNextFrame(byte[] buf) {
	    this.frameLock.lock();
	    this.frameData = buf;
		this.frameEnqueued = true;		
		this.frameLock.unlock();
	}


	/* (non-Javadoc)
	 * @see edu.dhbw.andopenglcam.interfaces.PreviewFrameSink#getFrameLock()
	 */
	public ReentrantLock getFrameLock() {
		return frameLock;
	}	
	
}

/**
 * write stuff to Android log
 * @author Tobias Domhan
 *
 */
class LogWriter extends Writer {

    @Override public void close() {
        flushBuilder();
    }

    @Override public void flush() {
        flushBuilder();
    }

    @Override public void write(char[] buf, int offset, int count) {
        for(int i = 0; i < count; i++) {
            char c = buf[offset + i];
            if ( c == '\n') {
                flushBuilder();
            }
            else {
                mBuilder.append(c);
            }
        }
    }

    private void flushBuilder() {
        if (mBuilder.length() > 0) {
            Log.e("OpenGLCam", mBuilder.toString());
            mBuilder.delete(0, mBuilder.length());
        }
    }

    private StringBuilder mBuilder = new StringBuilder();
    
    
}
